/********************************************
 * 功能说明: 
 * 模块名称: 
 * 系统名称: 
 * 软件版权: Frank
 * 系统版本: 1.0.0
 * 开发人员: Frank
 * 开发时间: 2019/12/14 18:20
 * 审核人员: 
 * 相关文档: 
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.spring.arch.uaa.service;

import com.spring.arch.common.enums.DataType;
import com.spring.arch.common.exception.ExceptionHolder;
import com.spring.arch.uaa.errorcode.UaaErrorCode;
import com.spring.arch.uaa.model.Authority;
import com.spring.arch.uaa.model.Role;
import com.spring.arch.uaa.model.RoleAuthority;
import com.spring.arch.common.enums.DataType;
import com.spring.arch.common.exception.ExceptionHolder;
import com.spring.arch.uaa.model.Authority;
import com.spring.arch.uaa.model.Role;
import com.spring.arch.uaa.model.RoleAuthority;
import com.spring.arch.uaa.repository.AuthorityRepository;
import com.spring.arch.uaa.repository.RoleAuthorityRepository;
import com.spring.arch.uaa.repository.RoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import static com.spring.arch.uaa.errorcode.UaaErrorCode.*;

/**
 * 角色服务层
 *
 * @author Frank
 * @version 1.0.0.1
 * @since 2019/12/14 18:20
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class RoleService {

    @Autowired
    private RoleRepository roleRepository;
    @Autowired
    private AuthorityRepository authorityRepository;
    @Autowired
    private RoleAuthorityRepository roleAuthorityRepository;

    public Role save(Role model, List<UUID> resourceIds) {
        boolean existsCode;
        if (model.isNew()) {
            existsCode = roleRepository.existsByCode(model.getCode());
        } else {
            existsCode = roleRepository.existsByCodeAndIdNot(model.getCode(), model.getId());
        }
        if (existsCode) {
            throw ExceptionHolder.serviceException(UaaErrorCode.E2001006004, model.getCode());
        }
        boolean existsName;
        if (model.isNew()) {
            existsName = roleRepository.existsByName(model.getName());
        } else {
            existsName = roleRepository.existsByNameAndIdNot(model.getName(), model.getId());
        }
        if (existsName) {
            throw ExceptionHolder.serviceException(UaaErrorCode.E2001006004, model.getName());
        }

        final Role role = roleRepository.save(model);
        // 写入资源
        if (!CollectionUtils.isEmpty(resourceIds) && DataType.INTERNAL.equals(role.getDataType())) {
            // 删除角色资源
            roleAuthorityRepository.deleteByRole(role);
            // 重新写入
            resourceIds.forEach(resourceId -> {
                Optional<Authority> optional = authorityRepository.findById(resourceId);
                optional.ifPresent(authority -> {
                    RoleAuthority roleAuthority = new RoleAuthority(role, authority);
                    roleAuthorityRepository.save(roleAuthority);
                });

            });
        }
        // 角色组合
        List<Role> internalRoles = role.getInternalRoles();
        if (!CollectionUtils.isEmpty(internalRoles) && DataType.CUSTOM.equals(role.getDataType())) {
            // 删除角色资源
            roleAuthorityRepository.deleteByRole(role);
            List<RoleAuthority> authorityList = roleAuthorityRepository.findByRoleIn(internalRoles);
            if (!CollectionUtils.isEmpty(authorityList)) {
                Set<Authority> authorities = authorityList.stream().map(RoleAuthority::getAuthority).collect(Collectors.toSet());
                if (!CollectionUtils.isEmpty(authorities)) {
                    authorities.forEach(authority -> {
                        RoleAuthority roleAuthority = new RoleAuthority(role, authority);
                        roleAuthorityRepository.save(roleAuthority);
                    });
                }
            }
        }

        return role;
    }

    public void delete(UUID id) {
        Role role = roleRepository.findById(id)
                .orElseThrow(() -> ExceptionHolder.serviceException(UaaErrorCode.E2001006001, String.valueOf(id)));
        if (DataType.INTERNAL.equals(role.getDataType())) {
            throw ExceptionHolder.serviceException(UaaErrorCode.E2001006003, "删除");
        }
        // 删除角色资源权限
        roleAuthorityRepository.deleteByRole(role);
        roleRepository.delete(role);
    }

    /**
     * 锁定角色
     * @param id 角色id
     */
    public void lock(UUID id) {
        Role role = roleRepository.findById(id)
                .orElseThrow(() -> ExceptionHolder.serviceException(UaaErrorCode.E2001006001, String.valueOf(id)));

        if (role.isDisable()) {
            role.setDisable(false);
        } else {
            role.setDisable(true);
        }
        roleRepository.save(role);
    }
}
